package com.sunxd.zstudy.juc;

import java.util.Random;

/**
 * @author: 同步锁
 * Synchronized 修饰普通方法 锁的是当前调用的对象
 *  同一个对象在两个线程中分别访问该对象的两个同步方法 互斥
 *  不同对象在两个线程中调用同一个同步方法 不互斥
 * Synchronized 修饰静态方法 锁的是整个类 （这个类里有2个Synchronized静态方法）
 *  用类直接在两个线程中调用两个不同的同步方法 互斥
 *  用一个类的静态对象在两个线程中调用静态方法或非静态方法 互斥
 *  一个对象在两个线程中分别调用一个静态同步方法和一个非静态同步方法 不互斥，锁不同
 *
 *  synchronized 实现：
 *  *      字节码： 0x0020 [synchronized] monitorenter,monitorexit,monitorexit 2条monitorexit，一个是正常推出另外一个是异常时退出
 *  *      JVM：C C++使用操作系统的锁方法
 *  *      硬件层面  ： Lock
 * @date: 2021-03-28 23:47
 **/
public class T05_Synchronized {

    public static void main(String[] args) {
        // 枷锁，保证count值更新
//        MyThread m = new MyThread();
//        for (int i = 0; i < 100; i++) {
//            new Thread(() -> m.update()).start();
//        }

        // 用String类型的变量，如果值都是同一个字符串，则第二个线程永远被阻塞。
        // 如果new String(),每次的字符串地址都不一样，导致同步失效
        new TestStringOrIntegerOrLong().testA();

    }

    static class TestStringOrIntegerOrLong{
        String a = "a";
        String b = "b";
        Object o = new Object();

        public  void testA(){
            new Thread(() ->{
                synchronized(a){
                    System.out.println(Thread.currentThread().getName()+" test b");
                    while (true){
                        try {
                            System.out.println(Thread.currentThread().getName()+" test b");
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            new Thread(() ->{
                synchronized(b){
                    System.out.println(Thread.currentThread().getName()+" test a");
                    while (true){
                        try {
                            System.out.println(Thread.currentThread().getName()+" test a");
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

        }

    }

    static class MyThread {
        public int count = 0;

         synchronized void update() {
             try {
                 Thread.sleep(new Random().nextInt(1)*100);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             count += 1;
            System.out.println("count=" + count);
        }
    }



}
